# -*- coding: UTF-8 -*-
 
# Python3.x 导入方法
import rsa
import time
import tkinter as tk
from tkinter.filedialog import (askopenfilename, 
                                askopenfilenames, 
                                askdirectory, 
                                asksaveasfilename)


#快速幂算法
def quick_pow(a, b):
    ans = 1
    while b != 0: # 判断b的二进制最后一位数是不是1，是则参与计算
        if b & 1:
            ans *= a
        b >>= 1
        a *= a
    return ans

#快速幂模算法
def quick_pow_mod(a, b, c):
    a = a % c
    ans = 1
    while b != 0: # 判断b的二进制最后一位数是不是1，是则参与计算
        if b & 1:
            ans = (ans * a) % c 
        b >>= 1
        a = (a * a) % c
    return ans

def getNewkey():
    (pubkey, privkey) = rsa.newkeys(4096)
    
    with open('公钥.e', 'w', encoding='utf-8') as f:
        f.truncate()
        print(f.write(str(pubkey['n'])+'\n'+str(pubkey['e'])))
    print(f.closed)
    with open('私钥.d', 'w', encoding='utf-8') as f:
        f.truncate()
        print(f.write(str(privkey['n'])+'\n'+str(privkey['d'])))
    print(f.closed)

    
def 加密文件():
    n = 0
    e = 0
    明文 = ""
    密文 = []
    
    公钥路径=askopenfilename(title='选择公钥',filetypes=[('公钥文件','*.e')])
    if 公钥路径 == '' or 公钥路径 == None:
        print('公钥路径错误')
        var.set('公钥路径错误QAQ')
        return

    文件路径=askopenfilename(title='选择文件',filetypes=[('文本文件','*.txt')])
    if 文件路径 == '' or 文件路径 == None:
        print('文件路径错误')
        var.set('文件路径错误QAQ')
        return
    
    with open(公钥路径, 'r', encoding='utf-8') as f:
        n = int(f.readline()[:-1])
        e = int(f.readline())
        #print(n,e)
    print('关闭公钥文件',f.closed)

    with open(文件路径, 'r', encoding='utf-8') as f:
        明文 = f.read()
    print('关闭文件',f.closed)

    for i in 明文.encode("utf-8"):
        c = quick_pow_mod(i, e, n)
        密文.append(str(c))
    with open('密文'+time.strftime("%Y%m%d-%H%M%S", time.localtime()) +'.txt', 'w', encoding='utf-8') as f:
        for i in 密文:
            f.write(i+'\n')
    print('关闭密文文件',f.closed)
    var.set('加密完成( ゜- ゜)つロ')
    
def 解密文件():
    n = 0
    d = 0
    明文 = []
    密文 = []
    
    私钥路径=askopenfilename(title='选择私钥',filetypes=[('私钥文件','*.d')])
    if 私钥路径 == '' or 私钥路径 == None:
        print('私钥路径错误')
        var.set('私钥路径错误QAQ')
        return False

    文件路径=askopenfilename(title='选择文件',filetypes=[('文本文件','*.txt')])
    if 文件路径 == '' or 文件路径 == None:
        print('文件路径错误')
        var.set('文件路径错误QAQ')
        return False
    
    with open(私钥路径, 'r', encoding='utf-8') as f:
        n = int(f.readline()[:-1])
        d = int(f.readline())
    print('关闭私钥文件',f.closed)

    with open(文件路径, 'r', encoding='utf-8') as f:

        while True:
            line = f.readline()
            if not line:
                break
            密文.append(int(line[:-1]))
            
    print('关闭文件',f.closed)

    for i in 密文:
        c=int(i)
        m = quick_pow_mod(c, d, n)
        明文.append(m)

    #print(bytes(明文).decode("utf-8"))
    
    with open('明文'+time.strftime("%Y%m%d-%H%M%S", time.localtime()) +'.txt', 'w', encoding='utf-8') as f:
        f.write(bytes(明文).decode("utf-8"))
    print('关闭明文文件',f.closed)
    var.set('解密完成( ゜- ゜)つロ')


top = tk.Tk()                     # 创建窗口对象的背景色
                                
top.title('RSA工具')

top.geometry('220x250')

var=tk.StringVar()#定义一个全局字符串变量
var.set('哈哈哈哈哈哈哈哈哈哈哈哈哈')
l = tk.Label(top, 
    textvariable=var,    # 标签的文字
    font=('Arial', 12),     # 字体和字体大小
    width=20, height=2  # 标签长宽
    )
l.place(x=25, y=200)    # 固定窗口位置


生成密钥按键 = tk.Button(top, 
    text='生成新密钥',      # 显示在按钮上的文字
    width=15, height=2, 
    command=getNewkey)     # 点击按钮式执行的命令
生成密钥按键.place(x=50, y=20)    # 按钮位置

加密按键 = tk.Button(top, 
    text='加密',      # 显示在按钮上的文字
    width=15, height=2, 
    command=加密文件)     # 点击按钮式执行的命令
加密按键.place(x=50, y=70)    # 按钮位置

解密按键 = tk.Button(top, 
    text='解密',      # 显示在按钮上的文字
    width=15, height=2, 
    command=解密文件)     # 点击按钮式执行的命令
解密按键.place(x=50, y=120)    # 按钮位置



top.mainloop()                 # 进入消息循环

